package stud.mpgame.snapshot;
import stud.mpgame.network.NetworkMonitor;

class SnapshotManager {
	
	private var localSnapshot:ISnapshot;
	private var nextServerSnapshots:List< ISnapshot >;
	private var commands:List< ICommand >;
	private var nextApplyCommandTime:Int;
	private var serverTickTime:Int;
	//?
	private var networkMonitor:NetworkMonitor;
	//?
	public function new(serverTickTime:Int, localSnapshot:ISnapshot, networkMonitor:NetworkMonitor) {
		this.serverTickTime = serverTickTime;
		this.localSnapshot = localSnapshot;
		//?
		this.networkMonitor = networkMonitor; 
		//?
		nextServerSnapshots = new List< ISnapshot >();
		commands = new List< ICommand >();
		nextApplyCommandTime = localSnapshot.getTime() + serverTickTime;
	}
	
	public function addServerSnapshot(snapshot:ISnapshot):Void {
		nextServerSnapshots.add(snapshot);
	}
	
	public function addCommand(command:ICommand):Void {
		commands.add(command);
	}
	
	public function update(deltaTime:Int):ISnapshot {
		if (nextServerSnapshots.isEmpty()) {
			localSnapshot = localSnapshot.extrapolate(deltaTime);
		}		
		if (!nextServerSnapshots.isEmpty() && nextServerSnapshots.first().getTime() >= networkMonitor.nowServerTime()) {
			localSnapshot = localSnapshot.synchronize(nextServerSnapshots.first());
			nextServerSnapshots.pop();
		}		
		var destinationServerSnapshot:ISnapshot = null;
		for (serverSnapshot in nextServerSnapshots) {
			if (serverSnapshot.getTime() >= needLocalSnapshotTime) {
				destinationServerSnapshot = serverSnapshot;
				break;
			}
		}
		//synchronize?
		if (destinationServerSnapshot == null) {
			var lastServerSnapshot:ISnapshot = nextServerSnapshots.last();
			destinationServerSnapshot = lastServerSnapshot.extrapolate((needLocalSnapshotTime - lastServerSnapshot.getTime()) * 2);
		}
		localSnapshot = localSnapshot.interpolate(deltaTime, destinationServerSnapshot);
		if (networkMonitor.nowServerTime() >= nextApplyCommandTime) {
			for (command in commands)
				command.apply(localSnapshot); //remove 
		}
		return localSnapshot;
	}
	
}